#include "Cube.h"

using Magick::Image;
using Magick::InitializeMagick;
namespace shapes{

	GLuint Cube::textureObjects[1];

	Cube::Cube()
		: ShapeNode(), quadric(0), height(0.5f), width(0.5f), depth(0.5f)
	{
		slices = 32;
		stacks = 32;
	}

	Cube::Cube(int ARGBvalues) 
		: ShapeNode(ARGBvalues), quadric(0), height(0.5f), width(0.5f), depth(0.5f), textured(false)
	{

	}


	Cube::Cube(float _width, float _height, float _depth, int ARGBvalues)
		: ShapeNode(ARGBvalues), quadric(0), width(_width), height(_height), depth(_depth), textured(false)
	{
		setColor(ARGBvalues);
	}

	Cube::Cube(Cube& cube) 
		: ShapeNode(cube.r, cube.g, cube.b, cube.alpha), 
		width(cube.width), height(cube.height), depth(cube.depth), quadric(0), textured(cube.textured)
	{
		slices = cube.slices;
		stacks = cube.stacks;
	}

	Cube::~Cube() {
		if ( quadric != 0 ) {
			gluDeleteQuadric( quadric );
		}
	}

	Cube& Cube::operator=(Cube& cube) 
	{
		slices = cube.slices;
		stacks = cube.stacks; 
		width  = cube.width;
		height = cube.height;
		depth  = cube.depth;
		// no need to change d_quadric
		return *this;
	}

	void Cube::draw() {
		ShapeNode::draw();
		if ( quadric == 0 ) {
			quadric = gluNewQuadric();
			gluQuadricDrawStyle( quadric, GLU_FILL );
			gluQuadricNormals( quadric, GLU_FLAT );
		}
		glColor3f( r, g, b);
		glScalef(width, height, depth);
		if(!textured){
			glutSolidCube(1.0f);
		} else {
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, textureObjects[currentTexture]);

			//we construct our own cubes for textured objects because glutSolidCubes
			//do not make texture mapping very simple or they typically look like garbage.
			renderCube();

			glDisable(GL_TEXTURE_2D);
		}

		ShapeNode::drawFinish();
	}

	void Cube::setTexture(char *fileName)
		{
		//we will just set our variables each time we call this function... kinda gross but it will
		//do for now.
		textureCount = 1;
		currentTexture = 0;
		if(glIsTexture(textureObjects[currentTexture]))	{ return; }

		glGenTextures(1, &textureObjects[0]);

		glPixelStorei(GL_UNPACK_ALIGNMENT, textureObjects[currentTexture]);
		//Bind texture
		glBindTexture( GL_TEXTURE_2D, textureObjects[currentTexture]);

		//Load the Image from disk
		Image image;
		image.read( fileName );
		image.flip();
		image.rotate(270.0);

		//setting up the texture environment
		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.columns(), image.rows(), 0,
			GL_BGRA_EXT,
			GL_UNSIGNED_SHORT, //16 bits per channel-- if ImageMagick was compiled as Q16
			image.getPixels(0, 0, image.columns(), image.rows()));

		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		}


	//Gotta thank NeHe for this one.
	//http://nehe.gamedev.net/
	void Cube::renderCube()
		{
		glBegin(GL_QUADS);
		// Front Face
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5f, -0.5f,  0.5f);	// Bottom Left Of The Texture and Quad
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.5f, -0.5f,  0.5f);	// Bottom Right Of The Texture and Quad
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.5f,  0.5f,  0.5f);	// Top Right Of The Texture and Quad
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f,  0.5f,  0.5f);	// Top Left Of The Texture and Quad
		// Back Face
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-0.50f, -0.50f, -0.50f);	// Bottom Right Of The Texture and Quad
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.50f,  0.50f, -0.50f);	// Top Right Of The Texture and Quad
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.50f,  0.50f, -0.50f);	// Top Left Of The Texture and Quad
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.50f, -0.50f, -0.50f);	// Bottom Left Of The Texture and Quad
		// Top Face
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.50f,  0.50f, -0.50f);	// Top Left Of The Texture and Quad
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.50f,  0.50f,  0.50f);	// Bottom Left Of The Texture and Quad
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.50f,  0.50f,  0.50f);	// Bottom Right Of The Texture and Quad
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.50f,  0.50f, -0.50f);	// Top Right Of The Texture and Quad
		// Bottom Face
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.50f, -0.50f, -0.50f);	// Top Right Of The Texture and Quad
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.50f, -0.50f, -0.50f);	// Top Left Of The Texture and Quad
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.50f, -0.50f,  0.50f);	// Bottom Left Of The Texture and Quad
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-0.50f, -0.50f,  0.50f);	// Bottom Right Of The Texture and Quad
		// Right face
		glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.50f, -0.50f, -0.50f);	// Bottom Right Of The Texture and Quad
		glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.50f,  0.50f, -0.50f);	// Top Right Of The Texture and Quad
		glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.50f,  0.50f,  0.50f);	// Top Left Of The Texture and Quad
		glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.50f, -0.50f,  0.50f);	// Bottom Left Of The Texture and Quad
		// Left Face
		glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.50f, -0.50f, -0.50f);	// Bottom Left Of The Texture and Quad
		glTexCoord2f(1.0f, 0.0f); glVertex3f(-0.50f, -0.50f,  0.50f);	// Bottom Right Of The Texture and Quad
		glTexCoord2f(1.0f, 1.0f); glVertex3f(-0.50f,  0.50f,  0.50f);	// Top Right Of The Texture and Quad
		glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.50f,  0.50f, -0.50f);	// Top Left Of The Texture and Quad
		glEnd();
		}
}